package org.garbagecan.hibernatestudy.util;

import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.type.Type;

public class HibernateUtil {

	private static Log log = LogFactory.getLog(HibernateUtil.class);

	private static HibernateUtil util = null;

	private HibernateUtil() {

	}

	public static HibernateUtil getInstance() {
		if (util == null) {
			util = new HibernateUtil();
		}
		return util;
	}

	public Object findById(int id, Class clazz) {
		Object object = null;
		Session s = null;

		try {
			s = HibernateSessionFactory.getInstance().getSession();
			object = s.get(clazz, new Integer(id));
		}
		catch (HibernateException he) {
			log.error("findById method Exception!", he);
		}
		finally {
			HibernateSessionFactory.getInstance().closeSession(s);
		}
		return object;
	}

	public Object findById(String id, Class clazz) {
		Object object = null;
		Session s = null;
		try {
			s = HibernateSessionFactory.getInstance().getSession();
			object = s.get(clazz, id);
		}
		catch (HibernateException he) {
			log.error("findById method Exception!", he);
		}
		finally {
			HibernateSessionFactory.getInstance().closeSession(s);
		}
		return object;
	}

	public Object add(Object object, Class clazz) {
		Session s = null;
		Transaction tx = null;
		try {
			s = HibernateSessionFactory.getInstance().getSession();
			tx = s.beginTransaction();
			s.save(object);
			tx.commit();
		}
		catch (HibernateException he) {
			rollback(tx);
			log.error("add method Exception!", he);
		}
		finally {
			HibernateSessionFactory.getInstance().closeSession(s);
		}
		return object;
	}

	public Object add(Object object) {
		Session s = null;
		Transaction tx = null;
		try {
			s = HibernateSessionFactory.getInstance().getSession();
			tx = s.beginTransaction();
			s.save(object);
			tx.commit();
		}
		catch (HibernateException he) {
			rollback(tx);
			log.error("add method Exception!", he);
		}
		finally {
			HibernateSessionFactory.getInstance().closeSession(s);
		}
		return object;
	}

	public Object[] add(Object[] objects) {
		Session s = null;
		Transaction tx = null;
		try {
			s = HibernateSessionFactory.getInstance().getSession();
			tx = s.beginTransaction();
			for (int i = 0; i < objects.length; i++) {
				s.save(objects[i]);
			}
			tx.commit();
		}
		catch (HibernateException he) {
			rollback(tx);
			log.error("add method Exception!", he);
		}
		finally {
			HibernateSessionFactory.getInstance().closeSession(s);
		}
		return objects;
	}

	public boolean remove(Object object) {
		Session s = null;
		Transaction tx = null;
		boolean blnret = true;
		try {
			s = HibernateSessionFactory.getInstance().getSession();
			tx = s.beginTransaction();
			s.delete(object);
			tx.commit();
		} catch (HibernateException he) {
			blnret = false;
			rollback(tx);
			log.error("remove method Exception!", he);
		} finally {
			HibernateSessionFactory.getInstance().closeSession(s);
		}
		return blnret;
	}

	public boolean remove(Object[] objects) {
		Session s = null;
		Transaction tx = null;
		boolean blnret = true;
		try {
			s = HibernateSessionFactory.getInstance().getSession();
			tx = s.beginTransaction();
			for (int i = 0; i < objects.length; i++) {
				s.delete(objects[i]);
			}
			tx.commit();
		} catch (HibernateException he) {
			blnret = false;
			rollback(tx);
			log.error("remove method Exception!", he);
		} finally {
			HibernateSessionFactory.getInstance().closeSession(s);
		}
		return blnret;
	}

	public boolean removeById(int id, Class clazz) {
		return remove(findById(id, clazz));
	}

	public boolean removeByIds(int[] ids, Class clazz) {
		Session s = null;
		Transaction tx = null;
		boolean blnRet = false;
		try {
			s = HibernateSessionFactory.getInstance().getSession();
			tx = s.beginTransaction();
			for (int i = 0; i < ids.length; i++) {
				Object object = s.get(clazz, new Integer(ids[i]));
				s.delete(object);
			}
			s.flush();
			tx.commit();
			blnRet = true;
		}
		catch (HibernateException he) {
			rollback(tx);
			log.error("object method Exception!", he);
		}
		finally {
			HibernateSessionFactory.getInstance().closeSession(s);
		}
		return blnRet;
	}

	public boolean removeById(String id, Class clazz) {
		return remove(findById(id, clazz));
	}

	public boolean removeByIds(String[] ids, Class clazz) {
		Session s = null;
		Transaction tx = null;
		boolean blnRet = false;
		try {
			s = HibernateSessionFactory.getInstance().getSession();
			tx = s.beginTransaction();
			for (int i = 0; i < ids.length; i++) {
				Object object = s.get(clazz, ids[i]);
				s.delete(object);
			}
			s.flush();
			tx.commit();
			blnRet = true;
		}
		catch (HibernateException he) {
			rollback(tx);
			log.error("object method Exception!", he);
		}
		finally {
			HibernateSessionFactory.getInstance().closeSession(s);
		}
		return blnRet;
	}

	public boolean removeAll(Class clazz) {
		Session s = null;
		Transaction tx = null;
		boolean blnRet = false;
		try {
			s = HibernateSessionFactory.getInstance().getSession();
			tx = s.beginTransaction();
			s.delete(" from " + clazz.getName());
			s.flush();
			tx.commit();
			blnRet = true;
		} catch (HibernateException he) {
			rollback(tx);
			log.error("update method Exception!", he);
		} finally {
			HibernateSessionFactory.getInstance().closeSession(s);
		}
		return blnRet;
	}

	public Object update(Object object) {
		Session s = null;
		Transaction tx = null;
		try {
			s = HibernateSessionFactory.getInstance().getSession();
			tx = s.beginTransaction();
			s.update(object);
			s.flush();
			tx.commit();
		}
		catch (HibernateException he) {
			rollback(tx);
			log.error("update method Exception!", he);
		}
		finally {
			HibernateSessionFactory.getInstance().closeSession(s);
		}
		return object;
	}

	public Object[] update(Object[] objects) {
		Session s = null;
		Transaction tx = null;
		try {
			s = HibernateSessionFactory.getInstance().getSession();
			tx = s.beginTransaction();
			for (int i = 0; i < objects.length; i++) {
				s.update(objects[i]);
			}
			s.flush();
			tx.commit();
		}
		catch (HibernateException he) {
			rollback(tx);
			log.error("update method Exception!", he);
		}
		finally {
			HibernateSessionFactory.getInstance().closeSession(s);
		}
		return objects;
	}

	/**
	 * HibernateUtil util = HibernateUtil.getInstance();
	 * List list ;
	 * list = util.list(" from User");
	 * list = util.list(" from User order by name desc");
	 */
	public List list(String hsql) {
		return list(hsql, new Object[0], new Type[0]);
	}

	/**
	 * HibernateUtil util = HibernateUtil.getInstance();
	 * List list ;
	 * list = util.list(" from User",0,10);
	 * list = util.list(" from DeparUsertment order by name desc",0,10);
	 */
	public List list(String hsql, int first, int size) {
		return list(hsql, new Object[0], new Type[0], first, size);
	}

	/**
	 * HibernateUtil util = HibernateUtil.getInstance();
	 * List list;
	 * String hsql = "from User where name=? order by name desc";
	 * Object []objs = new Object[]{"kongxx"};
	 * Type []types = new Type[]{new StringType()};
	 * list = util.list(hsql,objs,types);
	 */
	public List list(String hsql, Object[] objects, Type[] types) {
		return list(hsql, objects, types, 0, 0);
	}

	/**
	 * HibernateUtil util = HibernateUtil.getInstance();
	 * List list;
	 * String hsql = "from User where name=? order by name desc";
	 * Object []objs = new Object[]{"kongxx"};
	 * Type []types =  new Type[]{new StringType()};
	 * list = util.list(hsql,objs,types ,0,10);
	 */
	public List list(String hsql, Object[] objects, Type[] types,
					 int first, int size) {
		if (objects.length != types.length) {
			throw new IllegalArgumentException("the Object[] or Type[]'s lenth error!");
		}
		List list = null;
		Session s = null;
		Query q = null;
		try {
			s = HibernateSessionFactory.getInstance().getSession();
			q = s.createQuery(hsql);
			for (int i = 0; i < objects.length; i++) {
				q.setParameter(i, objects[i], types[i]);
			}

			//??????
			q.setFirstResult(first);

			//????????
			if (size != 0) {
				q.setMaxResults(size);
			}

			list = q.list();
		} catch (HibernateException he) {
			log.error("list method Exception!", he);
		} finally {
			HibernateSessionFactory.getInstance().closeSession(s);
		}
		return list;
	}

	/**
	 * HibernateUtil util = HibernateUtil.getInstance();
	 * List list;
	 * list = util.list(User.class);
	 */
	public List list(Class clazz) {
		return list(clazz, null);
	}

	/**
	 * HibernateUtil util = HibernateUtil.getInstance();
	 * List list;
	 * list = util.list(User.class ,null);
	 * list = util.list(User.class ,
	 * "where name = 'kongxx' order by name desc");
	 */
	public List list(Class clazz, String subhsql) {
		return list(clazz, subhsql, 0, 0);
	}

	/**
	 * HibernateUtil util = HibernateUtil.getInstance();
	 * List list;
	 * list = util.list(User.class ,0,10);
	 */
	public List list(Class clazz, int first, int size) {
		return list(clazz, null, first, size);
	}

	/**
	 * HibernateUtil util = HibernateUtil.getInstance();
	 * List list;
	 * list = util.list(User.class,null,0,10);
	 * list = util.list(User.class ,
	 * "where name = 'kongxx' order by name desc",0,10);
	 */
	public List list(Class clazz, String subhsql, int first, int size) {
		List list = null;
		Session s = null;
		Query q = null;
		try {
			s = HibernateSessionFactory.getInstance().getSession();

			String strQuery = " from " + clazz.getName() + " ";
			if (subhsql != null && subhsql.length() != 0) {
				strQuery += subhsql;
			}
			q = s.createQuery(strQuery);

			q.setFirstResult(first);

			if (size != 0) {
				q.setMaxResults(size);
			}

			list = q.list();
		}
		catch (HibernateException he) {
			log.error("list method Exception!", he);
		}
		finally {
			HibernateSessionFactory.getInstance().closeSession(s);
		}
		return list;
	}

	public String getSingleValue(String hsql, Object[] objects, Type[] types) {
		List list = null;
		Session s = null;
		Query q = null;
		String value = null;

		try {
			s = HibernateSessionFactory.getInstance().getSession();
			q = s.createQuery(hsql);
			for (int i = 0; i < objects.length; i++) {
				q.setParameter(i, objects[i], types[i]);
			}
			list = q.list();
			value = null;
			if (list.iterator().hasNext()) {
				if (list.iterator().next() != null) {
					value = list.iterator().next().toString();
				}
			}
		} catch (HibernateException he) {
			log.error("getSingleValue method Exception!", he);
		} finally {
			HibernateSessionFactory.getInstance().closeSession(s);
		}
		return value;
	}

	public int count(Class clazz) {
		return count(clazz, null);
	}

	public int count(Class clazz, String strWhere) {
		String strQuery = "select count(*) from " + clazz.getName();
		if (strWhere != null && strWhere.length() != 0) {
			strQuery += strWhere;
		}
		return count(strQuery);
	}

	public int count(String strQuery) {
		if (strQuery == null || strQuery.length() == 0) {
			throw new IllegalArgumentException("The Query is invalid!");
		}
		int count = 0;
		Session s = null;
		try {
			s = HibernateSessionFactory.getInstance().getSession();
			List list = list(strQuery);
			count = Integer.parseInt(list.iterator().next().toString());
		} catch (HibernateException he) {
			log.error("list method Exception!", he);
		} finally {
			HibernateSessionFactory.getInstance().closeSession(s);
		}
		return count;
	}

	public int count(String hsql, Object[] objects, Type[] types) {
		Session s = null;
		Query q = null;
		int count = 0;

		try {
			s = HibernateSessionFactory.getInstance().getSession();

			q = s.createQuery(hsql);
			for (int i = 0; i < objects.length; i++) {
				q.setParameter(i, objects[i], types[i]);
			}

			List list = q.list();
			count = Integer.parseInt(list.iterator().next().toString());
		} catch (HibernateException he) {
			log.error("count method Exception!", he);
		} finally {
			HibernateSessionFactory.getInstance().closeSession(s);
		}
		return count;
	}

	public void rollback(Transaction tx) {
		if (tx == null) return;
		try {
			tx.rollback();
		}
		catch (HibernateException e) {
			log.error("Transaction roolback Exception!", e);
		}
	}
}